{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "5b5d8070",
   "metadata": {},
   "source": [
    "--------\n",
    "\n",
    "* *记录人（学习人）：kaijun*\n",
    "\n",
    "* *时间：2021-11-25*\n",
    "\n",
    "* *关于函数与模块*\n",
    "\n",
    "--------"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "327f5b66",
   "metadata": {},
   "source": [
    "### [函数的定义](https://docs.python.org/zh-cn/3/tutorial/controlflow.html#defining-functions)\n",
    "1. 数学：     f(x) = ax + b\n",
    "2. python：def fib(x): \n",
    "3. *定义* 函数使用关键字 def，后跟函数名与括号内的形参列表。\n",
    "4. 数学思维 vs 编程思维\n",
    " 1. 数学思维是写在同一行的（定义函数 和 运算公式），面向对象编程中，函数写多行，定义函数为单独一行\n",
    " 2. 数学函数一般没有注释，但在编程过程中，一般需要对函数进行注释描述（docstring）\n",
    " 3. 在数学中，ax + b 是计算公式，而在编程中，我们将函数的内容称为**函数体**，函数体要有一定的**缩进**\n",
    " 4. 数学函数执行，将参数带入公式，编程中函数执行，将参数带入函数体\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "eb0ef22c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 斐波那契数列：0 1 1 2 3 5 8 13 21 ...\n",
    "\n",
    "# def:定义函数的关键字\n",
    "# flb：函数名\n",
    "# (n)：定义函数的参数\n",
    "\n",
    "def fib(n):\n",
    "     \"\"\"列出指定x以内的斐波那契数列\"\"\"\n",
    "     a, b = 0, 1\n",
    "     while a < n:\n",
    "         print(a, end=' ')\n",
    "         a, b = b, a+b\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "688bae0b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 "
     ]
    }
   ],
   "source": [
    "fib(2000)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "b377f0d2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 实践：写出一个\n",
    "\n",
    "def hello(name):\n",
    "    \"\"\"显示问候语\"\"\"\n",
    "    print(\"你好，%s同学~\"%(name))\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "e207093d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "你好，彬哥同学~\n"
     ]
    }
   ],
   "source": [
    "hello(\"彬哥\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5b343c47",
   "metadata": {},
   "source": [
    "### [函数的更多定义](https://docs.python.org/zh-cn/3/tutorial/controlflow.html#more-on-defining-functions)\n",
    "\n",
    "1. 调用函数/使用函数\n",
    " 1. 函数名(参数)\n",
    " 2. 参数可以不存在"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "f690401a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "time.struct_time(tm_year=2021, tm_mon=12, tm_mday=2, tm_hour=11, tm_min=26, tm_sec=34, tm_wday=3, tm_yday=336, tm_isdst=0)"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 回顾与思考\n",
    "import time\n",
    "\n",
    "# sleep() 需要给定一个时间（int）参数\n",
    "time.sleep(3)\n",
    "\n",
    "# localtime() 不需要给定参数\n",
    "time.localtime()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "905d99d3",
   "metadata": {},
   "source": [
    "### 函数的优势\n",
    "1. 可以重复使用相同的功能，避免重复造轮子\n",
    "2. 使用者可以不了解函数本身，只要清楚如何使用即可\n",
    "3. 使用/调用方便，只需清楚传递的函数以及参数"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "38ba26f8",
   "metadata": {},
   "source": [
    "### 函数的参数\n",
    "1. 形式参数（形参）\n",
    " 1. 在定义函数的时候定义的参数\n",
    " 2. 形参不占用内存\n",
    "2. 实际函数（实参）\n",
    " 1. 在调用函数的时候传递的参数\n",
    " 2. 调用函数时，形参分配空间，传递实参，执行函数内容"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "cbfb6cfe",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 课本函数实践案例\n",
    "def search4vowels(word):\n",
    "    \"\"\"显示文本中出现的元音字母有哪些\"\"\"\n",
    "    vowels = set(\"aeiou\")\n",
    "    word = set(word)\n",
    "    print(vowels & word)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "18c0915f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'u', 'i', 'e'}\n"
     ]
    }
   ],
   "source": [
    "search4vowels(\"hei,guys\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "10f7c373",
   "metadata": {},
   "source": [
    "#### 函数的类别\n",
    "1. 默认值参数\n",
    " 1. 调用参数时，可以省略传递的参数信息\n",
    " 2. \n",
    "2. 关键字参数\n",
    " 1. 在调用函数时，关键字参数可以不考虑形式参数的位置\n",
    "3. 位置参数\n",
    " 1. 在形式参数的定义中，有一定的先后顺序\n",
    " 2. 在调用参数时，要考虑形参的先后顺序\n",
    " 3. 调用函数时，不仅需要考虑参数位置，还需要考虑形式参数的个数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "417b03ad",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 位置参数👇\n",
    "\n",
    "def describe_pet(pet_name,animal_type):\n",
    "    \"\"\"显示宠物信息\"\"\"\n",
    "    print(\"\\nI have a \" + animal_type + \".\")\n",
    "    print(\"My \" + animal_type + \"'s name is \"+pet_name.title() + \".\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "be1d818b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "I have a dog.\n",
      "My dog's name is 旺财.\n"
     ]
    }
   ],
   "source": [
    "describe_pet(\"旺财\", \"dog\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "e1475a68",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "I have a cat.\n",
      "My cat's name is 妹妹.\n"
     ]
    }
   ],
   "source": [
    "# 关键字参数👇\n",
    "\n",
    "describe_pet(animal_type=\"cat\",pet_name=\"妹妹\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "3a2a8d97",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 默认值参数👇\n",
    "\n",
    "def describe_pet(pet_name,animal_type=\"dog\"):\n",
    "    \"\"\"显示宠物信息\"\"\"\n",
    "    print(\"\\nI have a \" + animal_type + \".\")\n",
    "    print(\"My \" + animal_type + \"'s name is \"+pet_name.title() + \".\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "e45efe8c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "I have a cat.\n",
      "My cat's name is 来福.\n"
     ]
    }
   ],
   "source": [
    "describe_pet(\"来福\",\"cat\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0a5abe01",
   "metadata": {},
   "source": [
    "#### 使用参数的注意事项\n",
    "1. 位置参数和关键字参数同时使用（调用函数）\n",
    " 1. 关键字参数都应该放在位置参数之后\n",
    " 2. 在1的基础上，多个关键字参数不考虑先后顺序"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "7d025953",
   "metadata": {},
   "outputs": [],
   "source": [
    "def test(x,y,z):\n",
    "    \"\"\"打印x，y，z的结果\"\"\"\n",
    "    print(x)\n",
    "    print(y)\n",
    "    print(z)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "5886a3cd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n",
      "3\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "# test(5,y=3,2)\n",
    "\n",
    "# 正确写法：\n",
    "test(5,3,z=2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "42f4716c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "5\n",
      "3\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "test(5,z=2,y=3)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3406e2d9",
   "metadata": {},
   "source": [
    "1. 非默认参数和默认参数同时使用（定义函数）\n",
    " 1. 默认参数都应该放在非默认参数之后"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "49f521f5",
   "metadata": {},
   "outputs": [],
   "source": [
    "def test(x,z,y=3):\n",
    "    \"\"\"打印x，y，z的结果\"\"\"\n",
    "    print(x)\n",
    "    print(y)\n",
    "    print(z)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "eb377fd4",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "570771e6",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
